#include "rc5.h"
#include "uart.h"
#include <util/delay.h>

uchar	rc5_bit = 0x00;				// bit value
uchar	rc5_time;				// count bit time
uint	rc5_tmp;				// shift bits in
uint	rc5_data;				// store result

rc5 read_rc5()
{
	cli();
	uint tmp = rc5_data;
	rc5_data = 0;
	sei();
	if(tmp) {
		rc5 rtrn = (rc5){
				(tmp >> 11 & 1), 
				(tmp >> 6 & 0x1F), 
				(tmp & 0x3F) | (~tmp >> 7 & 0x40)
				};
		return rtrn;
	} else {
		rc5 rtrn = (rc5){ 100, 0, 0 };
		return rtrn;
	}
}

SIGNAL (SIG_OVERFLOW0)
{
	uint tmp = rc5_tmp;			// for faster access
	TCNT0 = -2;				// 2 * 256 = 512 cycle

	if(++rc5_time > PULSE_MAX) {		// count pulse time
		// only if 14 bits received
		if(!(tmp & 0x4000) && (tmp & 0x2000)) {
			rc5_data = tmp;
		} 
		tmp = 0;
	}

	if((rc5_bit ^ xRC5_IN) & (1 << xRC5)) {		// change detect
		rc5_bit = ~rc5_bit;			// 0x00 -> 0xFF -> 0x00

		if(rc5_time < PULSE_MIN) {		// to short
			tmp = 0;
		}

		if(!tmp || rc5_time > PULSE_1_2) { // start or long pulse time
			if(!(tmp & 0x4000)) {	// not to many bits
				tmp <<= 1;	// shift
			}
			if(!(rc5_bit & 1 << xRC5)) {// inverted bit
				tmp |= 1;	// insert new bit
			}
			rc5_time = 0;		// count next pulse time
		}
	}

	rc5_tmp = tmp;
}

/*
 * Here begins the sender
 */

/*
#define MAX_COUNTER 	222
#define DUTY_CYCLE 	55
#define LED_PULSES 	32
#define TOGGLE_BIT	0x2000
#define PWM_L		OCR1A
#define PWM_R		OCR1B

uint8_t pulse_count = 0;		// ir-led pulse counter
uint8_t key_code = 0;			// actual key code
uint16_t code_to_send = 0;		// actual key code for transmitting
uint16_t pause_count = 0;		// counter for pause between two transm.
uint16_t last_transmcode = 0;		// last transmitted key code
uint16_t mask_to_send = 0x8000;		// bit masking
uint16_t toggle_bit = 0;		// toggle bit

void send_rc5(rc5 val)
{
	GIMSK = 0x00;
	//PWM1A
	TCCR1A = (1 << WGM10) | (2 << COM1A0);		// enable pwm
	TCCR1B = (1 << CS10);				// clk 16Mhz/256
	OCR1B = MAX_COUNTER;
	OCR1A = 0;
	sei();
	code_to_send = (3 << 14) | (val.addr << 8) | (val.value << 2);
	if(last_transmcode != code_to_send) {
		toggle_bit ^= TOGGLE_BIT;
	}
	last_transmcode = code_to_send;
	code_to_send |= toggle_bit;
	xSEND_OUT &= ~(1 << xSEND_LED);
	TIMSK |= (1 << OCIE1A);	 // enable timer1 overfl.
	while(TIMSK & (1 << OCIE1A));
}
*/

/*
SIGNAL (SIG_OUTPUT_COMPARE1A)
//ISR (TIMER1_CMPA_vect)
{
	//uart_puts("interrupt\n\r");
	// transmission finished => wait 64 bit times, resp. 4096 36Khz pulses
	if(mask_to_send == 0x0002) {
		pause_count++;
		pause_count &= 0x0FFF;
		xSEND_OUT |= (1 << xSEND_LED); // switch off led
		if(pause_count == 0x0000) {
			mask_to_send = 0x8000;
			OCR1A = 0x00;
			TIMSK &= ~(1 << OCIE1A); // timer1 overfl. dis.
		}
	} else {
		// send next bit...
		switch(pulse_count) {
			// send inverted data bit
		case 0x00:
			if((code_to_send & mask_to_send) == 0) {
				OCR1A = DUTY_CYCLE;
			} else {
				OCR1A = 0x00;
			}
			pulse_count++;
			break;
			// send non inverted data
		case LED_PULSES:
			if(OCR1A == 0x00) {
				OCR1A = DUTY_CYCLE;
			} else {
				OCR1A = 0x00;
			}
			pulse_count++;
			break;
			// prepare for next bit or stop
		case (2 * LED_PULSES):
			pulse_count = 0x00;
			OCR1A = 0x00;
			mask_to_send = (mask_to_send >> 1);
			break;
		default:
			pulse_count++;
		}
	}
};
*/


// Just to be shure...
#ifndef F_CPU
#define F_CPU 16000000
#endif

#define RC5_FREQU (36000)			// 36 kHz 
#define PRESCALER 1
#define INPUT (F_CPU / PRESCALER / RC5_FREQU)
#define HALF_VAL 32
#define MAX_VAL 63
#define INPUT2 444

uint16_t send_rc5data;
uint16_t counter = 0;
uint16_t mask_send;
uint16_t pulse_count = 0;

void send_rc5_int(uint16_t send_rc5data)
{
	uint16_t counter = 0;
	uint16_t mask_send =  ~(3 << 14);
	while(mask_send != 0 || counter != 0) {
		if(counter == 0) {
			mask_send >>= 1;
		}
		uint16_t bit = send_rc5data & (~mask_send);
		if(counter == MAX_VAL) {	// next bit plx
			send_rc5data &= mask_send;
		}
		bit = (bit > 0) ? 1 : 0;
		uint16_t send_pin = 0;
		if(counter > HALF_VAL) { // 2nd half
			if(bit == 1) {		// want to send? -> modulate
				//send_pin = modul & bit;
				send_pin = 1;
			} else { // don't want to send
				send_pin = 0;
			}
		} else {			// 1st half
			if(bit == 0) {
				//send_pin = modul | bit;
				send_pin = 1;
			} else {
				send_pin = 0;
			}
		}

		if(send_pin > 0) {
			xSEND_OUT |= (1 << xSEND_LED);  // pin on -> LED on
			_delay_us(9);
			xSEND_OUT &= ~(1 << xSEND_LED); // pin off -> LED off
			_delay_us(9);
			_delay_us(9);
		} else {
			xSEND_OUT &= ~(1 << xSEND_LED); // pin off -> LED off
			_delay_us(27);
		}
		counter = (counter + 1)%64;
	}
}	

void send_rc5(rc5 val)
{
	TCCR1B = (1 << CS10) | (1 << WGM12);
	//TCCR1A = (2 << COM1B0) | (1 << WGM10) /*| (1 << WGM11)*/;
	TCCR1A = 0;
	//TCCR1A =  (1 << WGM10);
	OCR1A = INPUT;
	OCR1B = 0;

	mask_send = ~(3 << 14);
	counter = 0;

	pulse_count = 0;
	send_rc5data = (3 << 12) | (val.addr << 6) | (val.value);
	/*
	cli();
	send_rc5_int(send_rc5data);
	sei();

	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(2);

	xSEND_OUT &= ~(1 << xSEND_LED); // pin off -> LED off
	return;
	*/

	TIMSK &= ~(1 << TOIE0);	// deactivate recv
	TIMSK |= (1 << OCIE1A);	// activate interrupt
	sei();
	while(TIMSK & (1 << OCIE1A));
	xSEND_OUT &= ~(1 << xSEND_LED); // pin off -> LED off
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	_delay_ms(16);
	//_delay_ms(16);
	//_delay_ms(16);
	//_delay_ms(2);
	_delay_ms(8);
	TIMSK |= (1 << TOIE0);	// activate recv
	//xSEND_OUT |= (1 << xSEND_LED);
}


SIGNAL(SIG_OUTPUT_COMPARE1A) 
{
	// all bits were sent
	if(mask_send == 0 && counter == 0) {
		TIMSK &= ~(1 << OCIE1A);
		return;
	}

	//uint16_t modul = (counter % 2) ? 0 : 1;
	if(counter == 0) {
		mask_send >>= 1;
	}
	uint16_t bit = send_rc5data & (~mask_send);
	if(counter == MAX_VAL) {	// next bit plx
		send_rc5data &= mask_send;
	}
	bit = (bit > 0) ? 1 : 0;
	uint16_t send_pin = 0;
	if(counter >= HALF_VAL) { // 2nd half
		if(bit == 1) {		// want to send? -> modulate
			//send_pin = modul & bit;
			send_pin = 1;
		} else { // don't want to send
			send_pin = 0;
		}
	} else {			// 1st half
		if(bit == 0) {
			//send_pin = modul | bit;
			send_pin = 1;
		} else {
			send_pin = 0;
		}
	}

	if(send_pin > 0) {
		xSEND_OUT |= (1 << xSEND_LED); // pin on -> LED on
		_delay_us(7);
		xSEND_OUT &= ~(1 << xSEND_LED);  // pin off -> LED off
		_delay_us(21);
	} else {
		xSEND_OUT &= ~(1 << xSEND_LED);  // pin off -> LED off
		_delay_us(28);
	}

	counter = (counter + 1) % 64;
}

/*
SIGNAL(SIG_OUTPUT_COMPARE1A) 
{
	// all bits were sent
	if(mask_send == 0 && counter == 0 && pulse_count == 0) {
		TIMSK &= ~(1 << OCIE1A);
		return;
	}

	//uint16_t modul = (counter % 2) ? 0 : 1;
	if(counter == 0 && pulse_count == 0) {
		mask_send >>= 1;
	}
	uint16_t bit = send_rc5data & (~mask_send);
	if(counter == MAX_VAL && pulse_count == 2) {	// next bit plx
		send_rc5data &= mask_send;
	}
	bit = (bit > 0) ? 1 : 0;
	uint16_t send_pin = 0;
	if(counter > HALF_VAL) { // 2nd half
		if(bit == 1) {		// want to send? -> modulate
			//send_pin = modul & bit;
			send_pin = 1;
		} else { // don't want to send
			send_pin = 0;
		}
	} else {			// 1st half
		if(bit == 0) {
			//send_pin = modul | bit;
			send_pin = 1;
		} else {
			send_pin = 0;
		}
	}

	if(send_pin > 0 && pulse_count == 0) {
		xSEND_OUT |= (1 << xSEND_LED);  // pin on -> LED on
	} else {
		xSEND_OUT &= ~(1 << xSEND_LED); // pin off -> LED off
	}

	if(pulse_count == 2) {
		counter = (counter + 1) % 64;
	}
	pulse_count = (pulse_count + 1) % 3;
}
*/


